package com.google.code.jcooky.rpc.compiler.java;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
import java.util.Map;

import com.google.code.jcooky.rpc.compiler.Compiler;
import com.google.code.jcooky.rpc.compiler.Processor;
import com.google.code.jcooky.rpc.compiler.java.parser.JavaParser;
import com.google.code.jcooky.rpc.compiler.java.parser.ParseException;

public class JavaCompiler implements Compiler {
	private Processor serviceProc, structProc, enumProc;
	private File folder;
	
	public JavaCompiler(File folder) throws IOException {
		this.folder = folder;
		
		serviceProc = new JavaServiceProcessor();
		structProc = new JavaStructProcessor();
		enumProc = new JavaEnumProcessor();
	}

	public void compile(Reader reader) throws IOException {
		
		JavaParser parser = new JavaParser(reader);
		File basedir = null;
		String namespace = null;
		
		try {
			StringBuffer strbuf = new StringBuffer(1024);
			Map<String, Object> parseMap = parser.parse();
			
			/** namespace process */
			if(parseMap.containsKey("namespaces")) {
				List<Map<String, Object>> namespaceList = (List<Map<String, Object>>) parseMap.get("namespaces");
				for(Map<String, Object> m : namespaceList)
				{
					if(m.containsKey("namespace_language") || m.get("namespace_language").equals("java")) {						
						/** file paths create */
						namespace = (String)m.get("namespace_package");
						String filePath = folder.getPath() + "/" + namespace.replaceAll("\\.", "/");
						basedir = new File(filePath);
						basedir.mkdirs();
					}
				}
			}
			
			/** struct process */
			if(parseMap.containsKey("structs")) {
				structProc.setNamespace(namespace);
				structProc.setBasedir(basedir);
				List<Map<String, Object>> structList = (List<Map<String, Object>>) parseMap.get("structs");
				for(Map<String, Object> m : structList) {
					structProc.process(m);
				}
			}
			
			/** service process */
			if (parseMap.containsKey("services")) {
				serviceProc.setNamespace(namespace);
				serviceProc.setBasedir(basedir);
				List<Map<String, Object>> serviceList = (List<Map<String, Object>>) parseMap.get("services");
				for(Map<String, Object> m : serviceList) {
					serviceProc.process(m);
				}
			}
			
			/** enum process */
			if(parseMap.containsKey("enums")) {
				enumProc.setNamespace(namespace);
				enumProc.setBasedir(basedir);
				List<Map<String, Object>> enumList = (List<Map<String, Object>>)parseMap.get("enums");
				for(Map<String, Object> m : enumList) {
					enumProc.process(m);
				}
			}
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}

}

// {services=[{methods=[{method_name=hello2,
// method_arguments=[{argument_type=string, argument_name=a},
// {argument_type=string, argument_name=b}], method_type=string},
// {method_name=hel
// lo, method_arguments=[], method_type=test_struct}, {method_name=testHello,
// method_arguments=[{argument_type=int, argument_name=id}], method_type=void}],
// sevice_name=test_service}],
// namespaces=[{namespace_package=com.google.code.jcooky,
// namespace_language=java}], structs=[{variables=[{var_name=a, var_type=int},
// {var_name=b, var_type=short}, {var_name=c, var_t
// ype=char}, {var_name=d, var_type=string}, {var_name=e, var_type=float},
// {var_name=f, var_type=double}, {var_name=g, var_type=bool}],
// struct_name=test_struct}]}